Modern automated memory management systems like garbage collectors ease the lifetime management of heap-allocated objects, as the garbage collection system automatically detects and reclaims heap objects that are no longer reachable by currently executing code. This automatism encourages software developers to utilize heap-allocated objects, as the later deletion of those objects and the reclaiming of memory used by those objects is performed automatically and is therefore not adding complexity to the code.
However, automated memory management comes at a price in form of higher CPU usage caused by garbage collection tasks, or temporal suspensions of the execution of user code during some critical garbage collection activities.
To reduce those adverse effects of automated memory management, first portions of code that are responsible for excessive creation of heap-allocated objects needs to be identified. After those code portions are identified, they may be redesigned to cause less heap-allocations.
A prerequisite of this optimization task is the visibility of performed object allocations by executing code, while the code is executed under “real-world” or production environments. A wide variety of commercial and non-commercial allocation monitoring tools exist, which either use a heap sampling-based or an instrumentation-based approach.
The heap-sampling approach is based on cyclic heap snapshots of the monitored heap memory, e.g. form of the types and quantities of objects that exist in the heap memory when the snapshot was acquired. Statistical data may be extracted from a sequence of heap snapshot, which may be used to identify memory usage tendencies, like a constantly rising number of objects of a specific type which can be used as an indicator of a memory leak. Variants of heap-sampling approaches may fetch additional information about the objects residing in the heap-memory, including references between objects and create a detailed model of the heap at sampling time. This detailed model may be used to identify undesired object references that keep objects from being collected by the garbage collector. The drawbacks of the sampling-based approach include a relatively high impact on the monitored system, as creating a memory snapshot may require to temporarily suspend all current code executions of the monitored process or application, a relatively high level of inaccuracy as objects allocated and reclaimed between two samples are not reported, and the lack of data describing the exact code portions that caused allocation activities. Due to those shortcomings, a sampling-based monitoring approach is capable to determine whether a heap-allocation caused problem exists or not, but it provides no data to identify and fix the root cause of such a problem.
The instrumentation-based approach scans code before its execution to identify allocation activities and places an allocation counter for each allocation activity that records the number of allocations performed, the type of object that was allocated and the position at which the allocation was performed, e.g. in form of a code line number of the allocation, a name of the method or function containing the allocation and a name of the class containing the method or function. The position data may also contain data identifying a thread context. Instrumentation-based approaches provide sufficient data to track down individual object allocations to the portion of code that caused those allocations, which is a prerequisite for efficient identification and correction of heap allocation caused performance problems.
However, the instrumentation-based approaches known in the art generate an amount of overhead that is not acceptable in production environments. The monitoring overhead can easily reach 100% or more in terms of CPU usage or response time and may even distort the allocation behavior of the monitored application. One reason for this high overhead is that automated memory management systems typically maintain a “compacted” heap memory layout that supports fast allocations. In a compacted heap, all allocated objects are aligned sequentially in the heap memory, and a pointer to a first memory address not used by an object is maintained. To reserve memory space for a new allocated object it is sufficient to increase this pointer by the size of the object. In such an optimized allocation environment, even a relatively small individual monitoring overhead like incrementing a counter may sum up to an intolerable amount of overall overhead.
Consequently, there is need in the art for an allocation monitoring approach that provides the same quality of data as conventional instrumentation-based approaches without causing the same amount of monitoring overhead.
This section provides background information related to the present disclosure which is not necessarily prior art.